
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.Container;

namespace Swaf.BizObj.basic
{
	[Serializable]
	public class FullBizObjSource : IBizObjSource
	{
		protected IDictionary m_lists;

		public FullBizObjSource(string info)
			:this(info, null)
		{
		}

		public FullBizObjSource(string info, string extraInfo)
		{
			m_lists = new ThreadSafeHashtable();
			if(info != null && info.Length != 0)
				populateFromXml(info, extraInfo);
		}

		public FullBizObjSource(IBizObjList list, string name)
		{
			if(name == null) name = "";

			m_lists = new ThreadSafeHashtable();
			m_lists[name] = list;
		}
		public FullBizObjSource(XmlElement ele, string catalogName)
		{
			m_lists = new ThreadSafeHashtable();
			XmlTextReader rdr=null;
			try
			{
				XmlNameTable nt = new NameTable();
				XmlNamespaceManager nsMgr = new XmlNamespaceManager(nt);
				XmlParserContext context = new XmlParserContext(nt, nsMgr, null,XmlSpace.None);
				rdr = new XmlTextReader(ele.OuterXml,XmlNodeType.Element,context);
				populateFromXmlStream(rdr, BaseBizObj.DefaultFieldDecoInfo);
			}
			catch(Exception e)
			{
				throw;
			}
			finally
			{
				rdr.Close();
			}
		}
		protected void populateFromXmlStream(XmlTextReader xmlIn, string extraInfo)
		{
			string rootNodeName = "";
			if(xmlIn.MoveToContent() == XmlNodeType.Element) 
			{
				rootNodeName = xmlIn.Name;
				IBizObjDefinition objType = Application.globalApp.bizObjMgr.checkForDefinition(rootNodeName);
				if(objType != null)
				{
					FullBizObjList list = (FullBizObjList)FullBizObjList.createInstance("", objType);
					IBizObj obj = extraInfo == null ? FullBizObj.createInstance("", objType, xmlIn) :
						FullBizObj.createInstance("", objType, xmlIn, extraInfo);
					list.Add(obj);
					m_lists[""] = list;
				}
				else
				{
					FullBizObjList list = extraInfo == null?
						(FullBizObjList)FullBizObjList.createInstance(null, this, xmlIn):
						(FullBizObjList)FullBizObjList.createInstance(null, this, xmlIn, extraInfo);

					m_lists[""] = list;
					if(list.Name != null)
						m_lists[list.Name] = list;
				}
			}

		}
		protected void populateFromXml(string xml, string extraInfo)
		{
			StringReader r = new StringReader(xml);
			XmlTextReader xmlIn = new XmlTextReader(r);
			try
			{
				populateFromXmlStream(xmlIn, extraInfo);
			}
			finally
			{
				xmlIn.Close();
				r.Close();
			}
		}

		protected internal IDictionary Lists { get { return m_lists; } }

		#region IBizObjSource Members

		public IBizObjList getList(string objType, string info)
		{
			string listName, sortInfo, filterInfo;
			calcGetListInfo(info, out listName, out sortInfo, out filterInfo);
			string fullListName = listName + sortInfo + filterInfo;

			IBizObjList list = null;
			if (!m_lists.Contains(fullListName))
			{
				if (!m_lists.Contains(listName) && sortInfo.Length == 0 && filterInfo.Length == 0)
				{
					list = FullBizObjList.createInstance(listName, Application.currentApp.bizObjMgr.getDefinition(objType), this);
					m_lists[listName] = list;
				}
				else if (m_lists.Contains(listName) && !(sortInfo.Length == 0 && filterInfo.Length == 0))
				{
					IBizObjList baseList = (IBizObjList)m_lists[listName];
					list = new IndexedFullBizObjList(baseList, sortInfo, filterInfo, false);
					m_lists[fullListName] = list;
				}
			}
			else
				list = (IBizObjList)m_lists[fullListName];

			return list;
		}

		public IBizObjCursor getCursor(string objType, string info)
		{
			IBizObjList l = getList(objType, info);
			if (l != null)
				return l.createCursor();
			return null;
		}

		public IBizObj getObject(string objType, string info)
		{
			return FullBizObj.createInstance(Application.currentApp.bizObjMgr.getDefinition(objType));
		}

		public IBizObj getObject(string objType, string fieldList, object searchValue)
		{
			return getObject(objType, fieldList, searchValue, false);
		}

		public IBizObj getObject(string objType, string fieldList, object searchValue, bool findNearestMatch)
		{
			IBizObjList list = getList(objType, fieldList);
			IComparable cmp = null;
            if (fieldList.Split(',').Length > 1)
            {
                // The list field is going to be multipart key so we need this to be 
                // multipart key but we'll force it to do a string sort compare
                // for backward compatibility purposes
                CompositeComparable cc = new CompositeComparable(false, true);
                cc.Add(searchValue);
                cmp = cc;
            }
            else
            {
                if (searchValue is IComparable)
                    cmp = (IComparable)searchValue;
                else if(searchValue != null)
                    cmp = searchValue.ToString();
            }
			if (list is IKeyedBizObjList && cmp != null)
			{
				IKeyedBizObjList indexedList = (IKeyedBizObjList)list;
				return indexedList.find(cmp, findNearestMatch);
			}

			return null;
		}

		public void Clear()
		{
			m_lists.Clear();
		}

		public void RemoveList(string name)
		{
			if (name != null && m_lists.Contains(name))
				m_lists.Remove(name);
		}

		public void AddList(IBizObjList newList)
		{
			m_lists[newList.Name] = newList;
		}

		#endregion
		protected void calcGetListInfo(string info, out string listName,
			out string sortInfo, out string filterInfo)
		{
			listName = "";
			sortInfo = "";
			filterInfo = "";

			if (info == null || info.Length == 0)
				return;

			string[] parts = info.Split(':');
			listName = parts[0];
			if (parts.Length >= 2)
				sortInfo = parts[1];
			if (parts.Length >= 3)
				filterInfo = parts[2];
		}
	}
}
